// -----------------------------------------------------------------------
//
//   Copyright (C) 2003-2006 Angel Marin
// 
//   This file is part of SharpMimeTools
//
//   SharpMimeTools is free software; you can redistribute it and/or
//   modify it under the terms of the GNU Lesser General Public
//   License as published by the Free Software Foundation; either
//   version 2.1 of the License, or (at your option) any later version.
//
//   SharpMimeTools is distributed in the hope that it will be useful,
//   but WITHOUT ANY WARRANTY; without even the implied warranty of
//   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
//   Lesser General Public License for more details.
//
//   You should have received a copy of the GNU Lesser General Public
//   License along with SharpMimeTools; if not, write to the Free Software
//   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
//
// -----------------------------------------------------------------------

using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;

namespace anmar.SharpMimeTools
{
	internal class SharpMimeAddressCollection : IEnumerable<SharpMimeAddress>
	{
		protected List<SharpMimeAddress> list = new List<SharpMimeAddress>();

		public SharpMimeAddressCollection(string text)
		{
			string[] tokens = anmar.SharpMimeTools.ABNF.address_regex.Split(text);
			foreach (string token in tokens)
			{
				if (anmar.SharpMimeTools.ABNF.address_regex.IsMatch(token))
					this.Add(new anmar.SharpMimeTools.SharpMimeAddress(token));
			}
		}

		public anmar.SharpMimeTools.SharpMimeAddress this[int index]
		{
			get
			{
				return this.Get(index);
			}
		}

		IEnumerator System.Collections.IEnumerable.GetEnumerator()
		{
			return list.GetEnumerator();
		}

		IEnumerator<SharpMimeAddress> IEnumerable<SharpMimeAddress>.GetEnumerator()
		{
			return list.GetEnumerator();
		}

		public void Add(SharpMimeAddress address)
		{
			list.Add(address);
		}

		public SharpMimeAddress Get(int index)
		{
			return (anmar.SharpMimeTools.SharpMimeAddress)list[index];
		}

		public static SharpMimeAddressCollection Parse(string text)
		{
			if (text == null)
			{
				throw new ArgumentNullException();
			}
			else
			{
				return new SharpMimeAddressCollection(text);
			}
		}

		public int Count
		{
			get
			{
				return list.Count;
			}
		}

		public override string ToString()
		{
			var text = new StringBuilder();
			foreach (SharpMimeAddress token in list)
			{
				text.Append(token.ToString());
				if (token.Length > 0)
				{
					text.Append("; ");
				}
			}

			return text.ToString();
		}
	}

	/// <summary>
	/// rfc 2822 email address
	/// </summary>
	public class SharpMimeAddress
	{
		private string displayName;
		private string address;

		/// <summary>
		/// Initializes a new address from a RFC 2822 name-addr specification string
		/// </summary>
		/// <param name="dir">RFC 2822 name-addr address</param>
		public SharpMimeAddress(string dir)
		{
			this.displayName = SharpMimeTools.parseFrom(dir, 1);
			this.address = SharpMimeTools.parseFrom(dir, 2);
		}

		/// <summary>
		/// Initializes a new address from a address and displayname
		/// </summary>
		/// <param name="address">The address.</param>
		/// <param name="displayName">The display name.</param>
		public SharpMimeAddress(string address, string displayName)
		{
			this.displayName = displayName;
			this.address = address;
		}

		public string DisplayName
		{
			get
			{
				return this["name"];
			}
		}

		public string Address
		{
			get
			{
				return this["address"];
			}
		}

		/// <summary>
		/// Gets the decoded address or name contained in the name-addr
		/// </summary>
		public string this[Object key]
		{
			get
			{
				if (key == null)
				{
					throw new System.ArgumentNullException();
				}

				switch (key.ToString())
				{
					case "0":
					case "name":
						return this.displayName;
					case "1":
					case "address":
						return this.address;
					default:
						break;
				}

				return null;
			}
		}

		/// <summary>
		/// 
		/// </summary>
		/// <returns></returns>
		public override string ToString()
		{
			if (string.IsNullOrEmpty(this.displayName) && string.IsNullOrEmpty(this.address))
				return string.Empty;

			if (string.IsNullOrEmpty(this.displayName))
			{
				return string.Format("<{0}>", this.address);
			}
			else
			{
				return string.Format("\"{0}\" <{1}>", this.displayName, this.address);
			}
		}

		/// <summary>
		/// Gets the length of the decoded address
		/// </summary>
		public int Length
		{
			get
			{
				return this.displayName.Length + this.address.Length;
			}
		}
	}
}
